#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
增强版龙头股分析器
基于原始龙头股分析器，增加低位龙头股识别功能
"""

import os
import json
import logging
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from pathlib import Path

# 导入基础分析器
from src.analyzers.leading_stock_analyzer import LeadingStockAnalyzer

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

class EnhancedLeadingStockAnalyzer(LeadingStockAnalyzer):
    """
    增强版龙头股分析器
    增加了低位龙头股识别和更多的数据分析功能
    """
    
    def __init__(self):
        """
        初始化增强版龙头股分析器
        """
        super().__init__()
        self.historical_price_data = {}
        self.industry_ranking = {}
        self.stock_data = {}  # 添加stock_data字典
        logger.info("增强版龙头股分析器初始化完成")
    
    def load_stock_data(self):
        """
        加载所有股票数据，包括基本面数据、财务数据和交易数据
        将所有数据整合到一个字典中，方便后续处理
        """
        logger.info("开始加载股票数据")
        try:
            # 获取股票目录
            stocks_dir = os.path.join(self.tushare_data_path, 'stocks')
            if not os.path.exists(stocks_dir):
                logger.warning(f"股票数据目录不存在: {stocks_dir}")
                return
                
            # 获取所有股票代码
            stock_codes = [d for d in os.listdir(stocks_dir) if os.path.isdir(os.path.join(stocks_dir, d))]
            logger.info(f"发现{len(stock_codes)}只股票数据")
            
            # 加载每只股票的数据
            loaded_count = 0
            for stock_code in stock_codes:
                try:
                    stock_data = self.collect_stock_data(stock_code)
                    if stock_data:
                        # 提取基本信息到顶层
                        basic_info = stock_data.get('basic', {})
                        if isinstance(basic_info, list) and len(basic_info) > 0:
                            basic_info = basic_info[0]
                            
                        financial_info = stock_data.get('financial', {})
                        if isinstance(financial_info, list) and len(financial_info) > 0:
                            financial_info = financial_info[0]
                            
                        valuation_info = stock_data.get('valuation', {})
                        if isinstance(valuation_info, list) and len(valuation_info) > 0:
                            valuation_info = valuation_info[0]
                        
                        # 整合关键指标到顶层
                        integrated_data = {
                            'code': stock_code,
                            'name': basic_info.get('name', ''),
                            'industry': basic_info.get('industry', ''),
                            'pe_ttm': float(valuation_info.get('pe_ttm', 0)),
                            'pb': float(valuation_info.get('pb', 0)),
                            'total_mv': float(valuation_info.get('total_mv', 0)) / 10000,  # 亿元
                            'circ_mv': float(valuation_info.get('circ_mv', 0)) / 10000,    # 亿元
                            'revenue': float(financial_info.get('revenue', 0)),
                            'net_profit': float(financial_info.get('net_profit', 0)),
                            'roe': float(financial_info.get('roe', 0)),
                            'eps': float(financial_info.get('eps', 0)),
                            'profit_to_gr': float(financial_info.get('profit_to_gr', 0)),
                            'price': float(valuation_info.get('close', 0)),
                            'income_yoy': float(financial_info.get('revenue_yoy', 0)), # 收入同比
                            'profit_yoy': float(financial_info.get('netprofit_yoy', 0)), # 利润同比
                        }
                        
                        # 存储完整数据 
                        self.stock_data[stock_code] = {**integrated_data, 'full_data': stock_data}
                        loaded_count += 1
                except Exception as e:
                    logger.error(f"加载股票 {stock_code} 数据失败: {e}")
                    continue
                    
            logger.info(f"成功加载{loaded_count}只股票的数据")
            
        except Exception as e:
            logger.error(f"加载股票数据失败: {e}")
    
    def load_historical_price_data(self):
        """
        加载股票历史价格数据
        """
        logger.info("加载股票历史价格数据")
        try:
            # 从data/price_history目录加载历史价格数据
            price_dir = os.path.join('data', 'price_history')
            if not os.path.exists(price_dir):
                logger.warning(f"历史价格数据目录不存在: {price_dir}")
                return
                
            for filename in os.listdir(price_dir):
                if filename.endswith('.json'):
                    file_path = os.path.join(price_dir, filename)
                    with open(file_path, 'r', encoding='utf-8') as f:
                        stock_data = json.load(f)
                        stock_code = filename.split('.')[0]
                        self.historical_price_data[stock_code] = stock_data
            
            logger.info(f"成功加载{len(self.historical_price_data)}只股票的历史价格数据")
        except Exception as e:
            logger.error(f"加载历史价格数据失败: {e}")
    
    def calculate_price_to_historical_ratio(self, stock_code, current_price=None):
        """
        计算当前价格相对历史高点的比例
        
        Args:
            stock_code: 股票代码
            current_price: 当前价格，如果为None则从市场数据中获取
            
        Returns:
            float: 价格比例，范围0-1，越小表示越低估
        """
        if not self.historical_price_data:
            self.load_historical_price_data()
        
        if stock_code not in self.historical_price_data:
            logger.warning(f"未找到股票{stock_code}的历史价格数据")
            return 1.0  # 默认返回1表示不低估
            
        try:
            price_history = self.historical_price_data[stock_code]
            if 'daily_prices' not in price_history:
                return 1.0
                
            # 获取历史最高价
            historical_high = max([day['high'] for day in price_history['daily_prices']])
            
            # 获取当前价格
            if current_price is None:
                # 从市场数据中获取当前价格
                stock_info = self.get_stock_data(stock_code)
                current_price = stock_info.get('price', 0)
                
            # 计算比例
            if historical_high > 0 and current_price > 0:
                return current_price / historical_high
            return 1.0
        except Exception as e:
            logger.error(f"计算价格比例失败: {e}")
            return 1.0
            
    def calculate_historical_rise(self, stock_code):
        """
        计算股票历史上的最大涨幅（从最低点到最高点）
        
        Args:
            stock_code: 股票代码
            
        Returns:
            float: 最大涨幅百分比
        """
        if not self.historical_price_data:
            self.load_historical_price_data()
            
        if stock_code not in self.historical_price_data:
            logger.warning(f"未找到股票{stock_code}的历史价格数据")
            return 0
            
        try:
            price_history = self.historical_price_data[stock_code]
            if 'daily_prices' not in price_history or not price_history['daily_prices']:
                return 0
                
            # 获取历史最高价和最低价
            historical_high = max([day['high'] for day in price_history['daily_prices']])
            historical_low = min([day['low'] for day in price_history['daily_prices'] if day['low'] > 0])
            
            # 计算最大涨幅
            if historical_low > 0:
                return ((historical_high - historical_low) / historical_low) * 100
            return 0
        except Exception as e:
            logger.error(f"计算历史涨幅失败: {e}")
            return 0
            
    def calculate_downtrend_days(self, stock_code):
        """
        计算股票当前下跌趋势持续的天数
        
        Args:
            stock_code: 股票代码
            
        Returns:
            int: 下跌趋势天数
        """
        if not self.historical_price_data:
            self.load_historical_price_data()
            
        if stock_code not in self.historical_price_data:
            logger.warning(f"未找到股票{stock_code}的历史价格数据")
            return 0
            
        try:
            price_history = self.historical_price_data[stock_code]
            if 'daily_prices' not in price_history or not price_history['daily_prices']:
                return 0
                
            # 获取最近的价格数据，按日期排序
            sorted_prices = sorted(price_history['daily_prices'], key=lambda x: x.get('date', ''), reverse=True)
            
            # 找到最近的最高点
            peak_idx = 0
            for i in range(1, min(180, len(sorted_prices))):
                if sorted_prices[i]['close'] > sorted_prices[peak_idx]['close']:
                    # 如果找到更高点，检查后面是否有明显下跌
                    downtrend = True
                    for j in range(i-1, -1, -1):
                        # 如果后面有价格回升点，不算明显下跌
                        if sorted_prices[j]['close'] >= sorted_prices[i]['close'] * 0.95:
                            downtrend = False
                            break
                    if downtrend:
                        peak_idx = i
            
            # 返回从高点至今的天数
            return peak_idx
        except Exception as e:
            logger.error(f"计算下跌趋势天数失败: {e}")
            return 0
            
    def get_industry_ranking(self, stock_code):
        """
        获取股票在行业中的排名
        
        Args:
            stock_code: 股票代码
            
        Returns:
            int: 行业排名，如不存在则返回999
        """
        if not self.industry_ranking:
            self.calculate_industry_rankings()
            
        stock_info = self.get_stock_data(stock_code)
        industry = stock_info.get('industry', '')
        
        if not industry or industry not in self.industry_ranking:
            return 999
            
        return self.industry_ranking[industry].get(stock_code, 999)
            
    def calculate_industry_rankings(self):
        """
        计算各行业内股票的排名
        基于市场份额、盈利能力等指标
        """
        logger.info("计算行业内股票排名")
        try:
            # 获取所有股票数据
            industry_data = {}
            
            for stock_code in self.stock_data:
                stock_info = self.stock_data[stock_code]
                industry = stock_info.get('industry', '')
                
                if not industry:
                    continue
                    
                if industry not in industry_data:
                    industry_data[industry] = []
                    
                # 计算综合得分（基于市值、利润、增长率等）
                market_value = stock_info.get('total_mv', 0)
                profit = stock_info.get('netprofit_ttm', 0)
                growth = stock_info.get('income_yoy', 0)
                
                # 简单加权得分
                score = market_value * 0.5 + profit * 0.3 + growth * 0.2
                
                industry_data[industry].append({
                    'code': stock_code,
                    'score': score
                })
                
            # 计算排名
            self.industry_ranking = {}
            for industry, stocks in industry_data.items():
                # 按得分排序
                sorted_stocks = sorted(stocks, key=lambda x: x['score'], reverse=True)
                
                # 记录排名
                self.industry_ranking[industry] = {}
                for i, stock in enumerate(sorted_stocks):
                    self.industry_ranking[industry][stock['code']] = i + 1
                    
            logger.info(f"成功计算{len(self.industry_ranking)}个行业的股票排名")
        except Exception as e:
            logger.error(f"计算行业排名失败: {e}")
            
    def calculate_average_liquidity(self, stock_code, days=30):
        """
        计算股票的平均日成交额
        
        Args:
            stock_code: 股票代码
            days: 计算天数
            
        Returns:
            float: 平均日成交额
        """
        if not self.historical_price_data:
            self.load_historical_price_data()
            
        if stock_code not in self.historical_price_data:
            logger.warning(f"未找到股票{stock_code}的历史价格数据")
            return 0
            
        try:
            price_history = self.historical_price_data[stock_code]
            if 'daily_prices' not in price_history or not price_history['daily_prices']:
                return 0
                
            # 获取最近的价格数据，按日期排序
            sorted_prices = sorted(price_history['daily_prices'], key=lambda x: x.get('date', ''), reverse=True)
            
            # 计算平均成交额
            volumes = [day.get('volume', 0) * day.get('close', 0) for day in sorted_prices[:days]]
            if volumes:
                return sum(volumes) / len(volumes)
            return 0
        except Exception as e:
            logger.error(f"计算平均成交额失败: {e}")
            return 0
            
    def find_low_position_leaders(self, criteria=None, top_n=10):
        """
        识别潜在的低位龙头股
        
        Args:
            criteria: 筛选标准
            top_n: 返回前N个结果
            
        Returns:
            list: 潜在的低位龙头股列表
        """
        logger.info("开始识别低位龙头股")
        
        # 默认筛选标准
        default_criteria = {
            'price_to_historical_ratio': 0.6,  # 当前价格不超过历史高点的60%
            'min_historical_rise': 100,        # 历史上至少有100%的涨幅
            'max_current_pe': 50,              # 当前PE不超过50
            'min_revenue_growth': 10,          # 收入增长至少10%
            'min_industry_rank': 5,            # 行业排名前5
            'min_liquidity': 5000000,          # 日均成交额至少500万
            'max_downtrend_days': 120          # 下跌趋势不超过120天
        }
        
        # 使用用户自定义筛选标准覆盖默认标准
        if criteria:
            for key, value in criteria.items():
                default_criteria[key] = value
                
        criteria = default_criteria
        
        try:
            # 加载必要数据
            if not self.stock_data:
                self.load_stock_data()
                
            if not self.historical_price_data:
                self.load_historical_price_data()
                
            if not self.industry_ranking:
                self.calculate_industry_rankings()
                
            # 候选列表
            candidates = []
            
            # 遍历所有股票
            for stock_code in self.stock_data:
                stock_info = self.stock_data[stock_code]
                
                # 基本筛选
                pe_ttm = stock_info.get('pe_ttm', 999)
                if pe_ttm > criteria['max_current_pe'] or pe_ttm <= 0:
                    continue
                    
                # 收入增长率
                income_yoy = stock_info.get('income_yoy', 0)
                if income_yoy < criteria['min_revenue_growth']:
                    continue
                    
                # 获取历史价格比例
                price_ratio = self.calculate_price_to_historical_ratio(stock_code)
                if price_ratio > criteria['price_to_historical_ratio']:
                    continue
                    
                # 历史涨幅
                historical_rise = self.calculate_historical_rise(stock_code)
                if historical_rise < criteria['min_historical_rise']:
                    continue
                    
                # 行业排名
                industry_rank = self.get_industry_ranking(stock_code)
                if industry_rank > criteria['min_industry_rank']:
                    continue
                    
                # 流动性
                liquidity = self.calculate_average_liquidity(stock_code)
                if liquidity < criteria['min_liquidity']:
                    continue
                    
                # 下跌趋势天数
                downtrend_days = self.calculate_downtrend_days(stock_code)
                if downtrend_days > criteria['max_downtrend_days']:
                    continue
                    
                # 使用高级多维度评分系统
                score_result = self.calculate_comprehensive_score(stock_code)
                total_score = score_result['total_score']
                score_components = score_result['score_components']
                
                # 添加到候选列表
                candidates.append({
                    'code': stock_code,
                    'name': stock_info.get('name', stock_code),
                    'industry': stock_info.get('industry', '未知'),
                    'price': stock_info.get('price', 0),
                    'pe_ttm': pe_ttm,
                    'price_to_historical_ratio': price_ratio,
                    'historical_rise': historical_rise,
                    'industry_rank': industry_rank,
                    'daily_liquidity': liquidity,
                    'downtrend_days': downtrend_days,
                    'income_yoy': income_yoy,
                    'growth_score': score_components['growth_score'],
                    'value_score': score_components['value_score'],
                    'technical_score': score_components['technical_score'],
                    'industry_score': score_components['industry_score'],
                    'undervalued_score': score_components['undervalued_score'],
                    'total_score': total_score
                })
                
            # 按总分排序
            candidates = sorted(candidates, key=lambda x: x['total_score'], reverse=True)
            
            # 返回前N个结果
            result = candidates[:top_n]
            
            # 保存结果
            self.save_low_position_leaders(result)
            
            logger.info(f"成功识别{len(result)}只潜在的低位龙头股")
            return result
            
        except Exception as e:
            logger.error(f"识别低位龙头股失败: {e}")
            return []
            
    def save_low_position_leaders(self, candidates):
        """
        保存低位龙头股分析结果
        
        Args:
            candidates: 候选股票列表
        """
        try:
            # 创建结果目录
            result_dir = os.path.join('data', 'results', 'low_position_leaders')
            os.makedirs(result_dir, exist_ok=True)
            
            # 保存JSON结果
            timestamp = datetime.now().strftime("%Y%m%d")
            json_path = os.path.join(result_dir, f'low_position_leaders_{timestamp}.json')
            
            with open(json_path, 'w', encoding='utf-8') as f:
                json.dump(candidates, f, ensure_ascii=False, indent=2)
                
            logger.info(f"低位龙头股分析结果已保存至: {json_path}")
            
            # 绘制综合评分条形图
            if candidates:
                self.visualize_low_position_leaders(candidates, result_dir)
                
        except Exception as e:
            logger.error(f"保存低位龙头股分析结果失败: {e}")
            
    def visualize_low_position_leaders(self, candidates, result_dir):
        """
        可视化低位龙头股分析结果
        
        Args:
            candidates: 候选股票列表
            result_dir: 结果保存目录
        """
        try:
            # 设置中文字体
            plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
            plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
            
            # 综合评分条形图
            plt.figure(figsize=(14, 8))
            names = [f"{stock['name']}({stock['code']})" for stock in candidates]
            scores = [stock['total_score'] for stock in candidates]
            
            # 颜色映射
            colors = plt.cm.YlGn(np.array(scores) / 100)
            
            plt.barh(names, scores, color=colors)
            plt.xlabel('综合评分')
            plt.title('低位龙头股评分排行')
            plt.grid(axis='x', linestyle='--', alpha=0.7)
            
            # 添加数值标签
            for i, score in enumerate(scores):
                plt.text(score + 1, i, f'{score:.1f}')
                
            # 保存图表
            chart_path = os.path.join(result_dir, 'low_position_leaders_scores.png')
            plt.savefig(chart_path, dpi=300, bbox_inches='tight')
            plt.close()
            
            # 绘制多维度雷达图
            if len(candidates) > 0:
                plt.figure(figsize=(12, 10))
                
                # 准备雷达图数据
                categories = ['成长性', '价值', '技术面', '行业地位', '低估程度']
                
                # 按综合评分筛选前3名股票显示
                top_stocks = candidates[:3]
                
                # 绘制雷达图
                angles = np.linspace(0, 2*np.pi, len(categories), endpoint=False).tolist()
                angles += angles[:1]  # 闭合
                
                ax = plt.subplot(111, polar=True)
                
                for i, stock in enumerate(top_stocks):
                    values = [
                        stock['growth_score'],
                        stock['value_score'],
                        stock['technical_score'],
                        stock['industry_score'],
                        stock['undervalued_score']
                    ]
                    values += values[:1]  # 闭合
                    
                    ax.plot(angles, values, linewidth=2, label=stock['name'])
                    ax.fill(angles, values, alpha=0.25)
                
                # 设置雷达图刻度和标签
                plt.xticks(angles[:-1], categories)
                plt.yticks([20, 40, 60, 80, 100], ['20', '40', '60', '80', '100'])
                plt.ylim(0, 100)
                
                plt.title('低位龙头股多维评分对比')
                plt.legend(loc='upper right')
                
                # 保存雷达图
                radar_path = os.path.join(result_dir, 'low_position_leaders_radar.png')
                plt.savefig(radar_path, dpi=300, bbox_inches='tight')
                plt.close()
                
            logger.info(f"低位龙头股分析图表已保存至目录: {result_dir}")
            
        except Exception as e:
            logger.error(f"可视化低位龙头股分析结果失败: {e}")
            
    def predict_next_low_position_leaders(self, count=5):
        """
        预测下一批可能崛起的低位龙头股
        
        Args:
            count: 预测数量
            
        Returns:
            list: 预测的低位龙头股列表
        """
        logger.info(f"开始预测下一批可能崛起的低位龙头股，数量: {count}")
        
        try:
            # 首先找到满足低位龙头股条件的候选股票
            candidates = self.find_low_position_leaders(top_n=20)
            
            if not candidates:
                logger.warning("未找到符合条件的低位龙头股候选")
                return []
                
            # 加载市场热点数据
            hot_industries = self.get_hot_industries()
            
            # 重新计算得分，加入行业热度因素
            for stock in candidates:
                industry = stock.get('industry', '')
                industry_heat = hot_industries.get(industry, 0)
                
                # 根据行业热度调整总分
                heat_bonus = min(20, industry_heat * 2)  # 最多加20分
                adjusted_score = stock['total_score'] + heat_bonus
                
                stock['industry_heat'] = industry_heat
                stock['heat_bonus'] = heat_bonus
                stock['adjusted_score'] = adjusted_score
                
            # 按调整后的分数重新排序
            candidates = sorted(candidates, key=lambda x: x['adjusted_score'], reverse=True)
            
            # 获取预测结果
            result = candidates[:count]
            
            # 保存预测结果
            timestamp = datetime.now().strftime("%Y%m%d")
            result_dir = os.path.join('data', 'results', 'low_position_leaders')
            os.makedirs(result_dir, exist_ok=True)
            
            json_path = os.path.join(result_dir, f'predicted_low_leaders_{timestamp}.json')
            with open(json_path, 'w', encoding='utf-8') as f:
                json.dump(result, f, ensure_ascii=False, indent=2)
                
            logger.info(f"预测的低位龙头股已保存至: {json_path}")
            
            # 可视化预测结果
            self.visualize_predicted_low_leaders(result, result_dir)
            
            return result
            
        except Exception as e:
            logger.error(f"预测低位龙头股失败: {e}")
            return []
            
    def visualize_predicted_low_leaders(self, predictions, result_dir):
        """
        可视化预测的低位龙头股
        
        Args:
            predictions: 预测的低位龙头股列表
            result_dir: 结果保存目录
        """
        try:
            # 设置中文字体
            plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
            plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
            
            # 创建图表
            plt.figure(figsize=(14, 10))
            
            # 准备数据
            names = [f"{stock['name']}({stock['code']})" for stock in predictions]
            scores = [stock['adjusted_score'] for stock in predictions]
            original_scores = [stock['total_score'] for stock in predictions]
            heat_bonus = [stock['heat_bonus'] for stock in predictions]
            
            # 创建堆叠条形图
            y_pos = range(len(names))
            
            # 绘制原始得分部分
            plt.barh(y_pos, original_scores, align='center', color='#3498db', label='基础评分')
            
            # 绘制热度加成部分
            plt.barh(y_pos, heat_bonus, align='center', color='#e74c3c', 
                    left=original_scores, label='行业热度加成')
            
            # 添加标签和标题
            plt.yticks(y_pos, names)
            plt.xlabel('预测得分')
            plt.title('预测的下一批低位龙头股')
            plt.legend()
            
            # 添加得分标签
            for i, (original, bonus) in enumerate(zip(original_scores, heat_bonus)):
                total = original + bonus
                plt.text(total + 1, i, f'{total:.1f}', va='center')
                
            # 调整布局
            plt.tight_layout()
            
            # 保存图表
            chart_path = os.path.join(result_dir, 'predicted_low_leaders.png')
            plt.savefig(chart_path, dpi=300, bbox_inches='tight')
            plt.close()
            
            # 绘制行业分布饼图
            industry_counts = {}
            for stock in predictions:
                industry = stock.get('industry', '未知')
                industry_counts[industry] = industry_counts.get(industry, 0) + 1
                
            plt.figure(figsize=(10, 8))
            plt.pie(industry_counts.values(), labels=industry_counts.keys(), autopct='%1.1f%%')
            plt.title('预测低位龙头股行业分布')
            pie_path = os.path.join(result_dir, 'predicted_low_leaders_industry.png')
            plt.savefig(pie_path, dpi=300, bbox_inches='tight')
            plt.close()
            
            logger.info(f"预测低位龙头股可视化结果已保存至目录: {result_dir}")
            
        except Exception as e:
            logger.error(f"可视化预测低位龙头股失败: {e}")
            
    def get_stock_data(self, stock_code):
        """
        获取股票数据，如果不存在则尝试收集
        
        Args:
            stock_code: 股票代码
            
        Returns:
            dict: 股票数据
        """
        if stock_code in self.stock_data:
            return self.stock_data[stock_code]
        
        # 收集股票数据
        stock_data = self.collect_stock_data(stock_code)
        
        # 提取关键指标
        if stock_data:
            extracted_data = {}
            
            # 从基本信息中提取
            if 'basic' in stock_data:
                basic = stock_data['basic']
                extracted_data['name'] = basic.get('name', '')
                extracted_data['industry'] = basic.get('industry', '')
                extracted_data['area'] = basic.get('area', '')
                
            # 从财务数据中提取
            if 'financial' in stock_data and 'income' in stock_data['financial']:
                income_data = stock_data['financial']['income']
                if income_data:
                    latest_income = income_data[0]
                    extracted_data['total_revenue'] = float(latest_income.get('total_revenue', 0) or 0)
                    extracted_data['operate_profit'] = float(latest_income.get('operate_profit', 0) or 0)
                    extracted_data['n_income'] = float(latest_income.get('n_income', 0) or 0)
                    
                    # 计算同比增长率
                    if len(income_data) > 4:  # 有上年同期数据
                        last_year_income = income_data[4]
                        last_year_revenue = float(last_year_income.get('total_revenue', 0) or 0)
                        if last_year_revenue > 0:
                            extracted_data['income_yoy'] = (extracted_data['total_revenue'] / last_year_revenue - 1) * 100
            
            # 从估值数据中提取
            if 'valuation' in stock_data and 'valuation' in stock_data['valuation']:
                valuation_data = stock_data['valuation']['valuation']
                if valuation_data:
                    latest_valuation = valuation_data[0]
                    extracted_data['pe_ttm'] = float(latest_valuation.get('pe_ttm', 0) or 0)
                    extracted_data['pb'] = float(latest_valuation.get('pb', 0) or 0)
                    extracted_data['ps_ttm'] = float(latest_valuation.get('ps_ttm', 0) or 0)
                    extracted_data['total_mv'] = float(latest_valuation.get('total_mv', 0) or 0) / 10000  # 亿元
                    extracted_data['circ_mv'] = float(latest_valuation.get('circ_mv', 0) or 0) / 10000  # 亿元
            
            # 价格信息
            if 'trading' in stock_data and 'daily' in stock_data['trading']:
                trading_data = stock_data['trading']['daily']
                if trading_data:
                    latest_trade = trading_data[0]
                    extracted_data['price'] = float(latest_trade.get('close', 0) or 0)
            
            # 保存提取的数据
            self.stock_data[stock_code] = extracted_data
            return extracted_data
        
        return {} 